package com.glsc.ngateway.flowable.amqp;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.common.dto.AppendIdDto;
import com.glsc.ngateway.common.api.flowable.dto.demand.FlowableDemandDto;
import com.glsc.ngateway.common.api.oaflow.dto.param.ParamOaLoginDto;
import com.glsc.ngateway.common.api.oaflow.resp.CommonResponse;
import com.glsc.ngateway.common.api.oaflow.resp.ResponseLoginDto;
import com.glsc.ngateway.common.base.domain.mysql.flowable.FlowableAppend;
import com.glsc.ngateway.common.base.repo.mysql.flowable.FlowableAppendRepo;
import com.glsc.ngateway.flowable.service.FlowableDemandService;
import com.glsc.ngateway.flowable.service.feignservice.OaflowFeignService;
import com.glsc.ngateway.flowable.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;

@Component
public class DemandOaReceiver {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final String demandQueue = "gateway.queue.fwFlow.demand";
    @Autowired
    private TaskService taskService;
    @Autowired
    private FlowableDemandService flowableDemandService;
    @Autowired
    private OaflowFeignService oaflowFeignService;
    @Autowired
    FlowableAppendRepo appendRepo;

    @Value("${oalogin.userId}")
    private String userId;
    @Value("${oalogin.password}")
    private String password;

    @Value("${oa.host}")
    private String oaHost;

    private static final String DESCRIPTION_REJECT = "退回";
    private static final String DESCRIPTION_AGREE = "流程结束";

    private Random random = new Random();

    /**
     * JSON格式：workflowId:111,requestId:123456789,workflowName:测试流程标题,description:success
     */
    @RabbitListener(queues = {demandQueue})
    @RabbitHandler
    public void processMessage(Message messageObject) throws IOException, NoSuchFieldException, IllegalAccessException {
        try {
            String message = new String(messageObject.getBody());
            logger.info("gateway.queue.fwFlow.demand,消息队列收到消息，message receiver:" + message);
            JSONObject msgJsonObject = JSONObject.parseObject(message);
            String workflowId = msgJsonObject.getString("workflowId");
            String requestId = msgJsonObject.getString("requestId");
            String workflowName = msgJsonObject.getString("workflowName");
            String description = msgJsonObject.getString("description");

            List<FlowableDemandDto> list = flowableDemandService.findByRequestId(requestId);
            if (list != null && list.size() > 0) {
                String processId = list.get(0).getProcessInstanceId();
                Task task = taskService.createTaskQuery().processInstanceId(processId).taskDefinitionKey("createoaTask").singleResult();
                if (task != null) {
                    //将oa流程表单生成pdf并保存
                    createPdfFile(requestId, workflowName);
                    if (DESCRIPTION_AGREE.equals(description)) {
                        Authentication.setAuthenticatedUserId("admin");
                        taskService.addComment(task.getId(), processId, "需求确认");
                    } else if (DESCRIPTION_REJECT.equals(description)) {
                        Authentication.setAuthenticatedUserId("admin");
                        taskService.addComment(task.getId(), processId, "需求拒绝，请关注OA流程确认文档");
                        //归档接口
                        oaflowFeignService.endOaFlow(requestId);
                    }
                    taskService.complete(task.getId());
                }
            }
        } catch (Exception e) {
            logger.error("demand，消费消息队列异常", e);
        }
    }

    private void createPdfFile(String requestId, String workflowName) throws IOException {
        List<MultipartFile> beforeFileList = new ArrayList<>();
        String srcPath = oaHost + "/spa/workflow/static4form/index.html?#/main/workflow/req?requestid=" + requestId + "&&ismonitor=1&isprint=1";
        String sessionId = getOaLoginSessionId();
        logger.info("模拟登录OA系统获取到SessionId:" + sessionId);
        if (StringUtils.isEmpty(sessionId)) {
            logger.error("模拟登录还是没有获取到sessionId，模拟登录OA系统获取到SessionId为空");
            return;
        }
        ResponseEntity<byte[]> responseEntity = null;
        for (int i = 0; i < 3; i++) {
            try {
                responseEntity = oaflowFeignService.getOaFlowPdf(srcPath, sessionId);
            } catch (Exception e) {
                logger.error("获取流程PDF文件流异常", e);
            }
            if (responseEntity == null || responseEntity.getBody() == null || responseEntity.getBody().length <= 50) {
                try {
                    int sleepTime = random.nextInt(6);
                    Thread.sleep(sleepTime * 1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
            } else {
                break;
            }
        }
        if (responseEntity == null || responseEntity.getBody() == null || responseEntity.getBody().length <= 50) {
            logger.info("经过三次重试没有获取到文件流，获取流程PDF文件流异常");
            return;
        }
        workflowName = workflowName + ".pdf";
        MultipartFile multipartFile = new MockMultipartFile("file", workflowName, ContentType.APPLICATION_OCTET_STREAM.toString(), new ByteArrayInputStream(responseEntity.getBody()));
        beforeFileList.add(multipartFile);

        MultipartFile[] uploadFileArray = new MultipartFile[beforeFileList.size()];
        for (int i = 0; i < uploadFileArray.length; i++) {
            uploadFileArray[i] = beforeFileList.get(i);
        }
        //调用网关批量文件上传接口
        String ret = oaflowFeignService.uploadDoc(uploadFileArray);
        logger.info("调用网关批量文件上传到网关接口返回报文信息:" + ret);
//{"code":0,"data":[{"annexId":"http://10.1.81.200:10003/oaDownloadAppendix/b5e093cc-45f0-4421-93fb-dc09829ff0af","annexName":"需求确认流程-国联技术服务平台-2022-04-26.pdf"}],"status":"SUCCESS"}
        List<AppendIdDto> newdto = new ArrayList<>();
        JSONObject jsonObject = JSONObject.parseObject(ret);
        String data = jsonObject.getString("data");
        List<AppendIdDto> fList = JSON.parseArray(data, AppendIdDto.class);
        String[] temp = fList.get(0).getAnnexId().split("\\/");
        String uuid = temp[temp.length - 1];
        AppendIdDto dto = new AppendIdDto();
        dto.setAnnexId(uuid);
        dto.setAnnexName(fList.get(0).getAnnexName());
        newdto.add(dto);

        //通过flowable上传附件用20220101格式
        //通过oaflow上传附件用2022-01-01格式  要注意
        //oapdf通过oaflowFeignService上传，所以在同步的时候要用oaflow的格式
        //已经统一成20220101格式了
        String today = DateUtil.today();
        String resPath = "/opt/ngateway/oaflow/uploaded_files/" + today + "/" + uuid + "/" + fList.get(0).getAnnexName();
        appendRepo.save(FlowableAppend.builder()
                .appendixName(fList.get(0).getAnnexName())
                .appendixPath(resPath)
                .appendixId(uuid)
                .build());
        List<FlowableDemandDto> list = flowableDemandService.findByRequestId(requestId);
        if (list != null && list.size() > 0) {
            FlowableDemandDto demand = list.get(0);
            demand.setOaPdfFile(JSON.toJSONString(newdto));
            flowableDemandService.saveDemandSubmit(demand);
        }
    }

    /*
     * 模拟登录OA系统获取SessionId
     * */
    private String getOaLoginSessionId() {
        logger.info("开始进行模拟登录OA系统获取SessionId");
        logger.info("OA系统登录用户名和密码,loginId:{},password:{}", userId, password);
        String oaSessionId = null;
        for (int i = 0; i < 3; i++) {
            ParamOaLoginDto paramOaLoginDto = new ParamOaLoginDto(userId, password);
            CommonResponse<ResponseLoginDto> ret = oaflowFeignService.oaLogin(paramOaLoginDto);
            if (Objects.isNull(ret.getData()) || StringUtils.isBlank(ret.getData().getSessionId())) {
                try {
                    int sleepTime = random.nextInt(6);
                    Thread.sleep(sleepTime * 1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
            } else {
                oaSessionId = ret.getData().getSessionId();
                break;
            }
        }
        return oaSessionId;
    }


}
